package com.newstore.database;

import java.util.HashMap;
import java.util.Map;
import java.util.Vector;

import android.content.ContentValues;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;

import com.newstore.classes.Barcode;
import com.newstore.classes.Order;
import com.newstore.classes.Product;

/**
 * Permet de faire le lien entre les objets Order et la base de données
 * @author Guillaume
 * @version 1.0
 */
public class OrderDatabase
{
	private SQLiteDatabase databaseQueries;
	private DeliveryDatabase deliveryDatabase;
	private BarcodeDatabase barcodeDatabase;
	
	/**
	 * Constructeur
	 * @param databaseQueries Base de données où les requêtes vont s'effectuer
	 */
	public OrderDatabase(SQLiteDatabase databaseQueries)
	{
		this.databaseQueries = databaseQueries;
		this.deliveryDatabase = new DeliveryDatabase(databaseQueries);
		this.barcodeDatabase = new BarcodeDatabase(databaseQueries);
	}
	
	/**
	 * Effectue une requête pour retourner un Delivery à partir d'un id
	 * @param orderId Id du barcode souhaité
	 * @return Le delivery souhaité
	 */
	public Order getOrderFromId(int orderId)
	{
		Cursor cursorOrder = databaseQueries.query(DatabaseNewstore.TABLE_ORDER, new String[] {"id", DatabaseNewstore.COL_STATUS, DatabaseNewstore.COL_ORDER_REFERENCE, DatabaseNewstore.COL_ORDER_BARCODE,
				DatabaseNewstore.COL_DELIVERY}, "id = " + orderId, null, null, null, null);
		Cursor cursorToBeIn = databaseQueries.query(DatabaseNewstore.TABLE_TOBEIN, new String [] {DatabaseNewstore.COL_PRODUCT, DatabaseNewstore.COL_NUMBERPRODUCT}, 
				DatabaseNewstore.COL_COMMAND + " = " + orderId, null, null, null, null);
		return orderCursor(cursorOrder, cursorToBeIn);
	}
	
	/**
	 * Permet de récupérer un order à partir d'un barcode
	 * @param barcode
	 * @return
	 */
	public Order getOrderFromBarcode(Barcode barcode)
	{
		int idBarcode = this.barcodeDatabase.getBarcodeFromBarcode(barcode).getId();
		Cursor cursorOrder = databaseQueries.query(DatabaseNewstore.TABLE_ORDER, new String[] {"id"}, DatabaseNewstore.COL_ORDER_BARCODE + " = " + idBarcode, null, null, null, null);
		cursorOrder.moveToNext();
		return this.getOrderFromId(cursorOrder.getInt(0));
	}
	
	/**
	 * Insère un order dans la base de données
	 * @param order order que l'on souhaite insérer dans la base de données
	 * @return L'id du order inséré
	 */
	public int insertOrder(Order order)
	{
		// Insert des éléments barcode et delivery : Le destinataire n'est pas généré avant insertion, il existe déjà, on va donc mettre directement son id dans la table Order
		// Au niveau du barcode, lui est généré. On va donc récupérer l'id lors de son insertion dans la base de données et le mettre dans la table Order
		ContentValues values = new ContentValues();
		values.put(DatabaseNewstore.COL_ORDER_REFERENCE, order.getReference());
	//	values.put(DatabaseNewstore.COL_STATUS, order.getStatus().getValue());
		values.put(DatabaseNewstore.COL_STATUS, order.getStatus());
	//	values.put(DatabaseNewstore.COL_ORDER_BARCODE, this.barcodeDatabase.insertBarcode(order.getBarcode()));
		values.put(DatabaseNewstore.COL_DELIVERY, order.getDelivery().getId());
		
		int idNewOrder = (int)this.databaseQueries.insert(DatabaseNewstore.TABLE_ORDER, null, values);

		// Ajout des produits de la commande dans la table ToBeIn qui fait le lien entre la commande et tous les produits
		for (HashMap<Product, Integer> productMap : order.getContentOrder())
		{
			ContentValues valuesMap = new ContentValues();
			for (Map.Entry<Product, Integer> coveringMap : productMap.entrySet())
			{
				valuesMap.put(DatabaseNewstore.COL_COMMAND, idNewOrder);
				valuesMap.put(DatabaseNewstore.COL_PRODUCT, coveringMap.getKey().getId());
				valuesMap.put(DatabaseNewstore.COL_NUMBERPRODUCT, (int)coveringMap.getValue());
			}
			this.databaseQueries.insert(DatabaseNewstore.TABLE_TOBEIN, null, valuesMap);
		}
		
		return idNewOrder;
	}	
	
	/**
	 * Obtient toutes les commandes qui sont en attente
	 * @return Une liste des commandes en attente
	 */
	public Vector<Order> getOrdersInHold()
	{
		//Pour que �a fonctionne : 
		//Cursor cursor = databaseQueries.query(DatabaseNewstore.TABLE_ORDER, new String[] { "id" }, null, null, null, null, null);
		
		Cursor cursor = databaseQueries.query(DatabaseNewstore.TABLE_ORDER, new String[] { "id" }, "status = \"En attente\"", null, null, null, null);
		Vector<Integer> listIds = new Vector<Integer>();
		Vector<Order> listOrders = new Vector<Order>();
		
		while (cursor.moveToNext())
		{
			listIds.add(cursor.getInt(0));
		}
		cursor.close();

		for (Integer id : listIds)
		{
			listOrders.add(this.getOrderFromId(id));
		}
		
		return listOrders;
	}
	
	/**
	 * Modifie le statut de la commande à partir de l'id
	 * @param orderId Id de la commande à update
	 * @param statusEnum String du status
	 * @return Le nombre de colonnes affectées
	 */
	public long updateStatusOrderFromId(int orderId, String statusEnum)
	{
		ContentValues values = new ContentValues();
		
		values.put(DatabaseNewstore.COL_STATUS, statusEnum);
		return this.databaseQueries.update(DatabaseNewstore.TABLE_ORDER, values, "id = " + orderId, null); 
	}
	
	/**
	 * Mise à jour de l'order avec le barcode
	 * @param orderId Id de la commande à mettre à jour
	 * @param barcodeId Id du code-barres à mettre dans la commande
	 * @return Le nombre de colonnes affectées
	 */
	public long updateBarcodeOrderFromId(int orderId, int barcodeId)
	{
		ContentValues values = new ContentValues();
		
		values.put(DatabaseNewstore.COL_ORDER_BARCODE, barcodeId);
		return this.databaseQueries.update(DatabaseNewstore.TABLE_ORDER, values, "id = " + orderId, null);
	}
	
	/**
	 * Cursor qui permet d'avoir un order grâce à une requête
	 * @param cursorOrder Cursor qui permet de parcourir la requête sur les commandes
	 * @param cursorToBeIn Cursor qui permet de parcourir la requête sur la table ToBeIn
	 * @return Le order rempli 
	 */
	private Order orderCursor(Cursor cursorOrder, Cursor cursorToBeIn)
	{
		if (cursorOrder.getCount() == 0 && cursorToBeIn.getCount() == 0)
			return null;
		
		cursorOrder.moveToFirst();
		Order order = new Order();
		// Construction de la commande sans les produits
		order.setId(cursorOrder.getInt(0));
		// Pour que �a fonctionne :
		//order.setStatus(StatusEnum.IN_HOLD);
		order.setStatus(cursorOrder.getString(1));
		order.setReference(cursorOrder.getString(2));
		int barcodeId = cursorOrder.getInt(3);
		int deliveryId = cursorOrder.getInt(4);
		cursorOrder.close();
		
		// Ajout du barcode et du delivery dans la commande
		order.setDelivery(this.deliveryDatabase.getDeliveryFromId(deliveryId));
		order.setBarcode(this.barcodeDatabase.getBarcodeFromId(barcodeId));
		
		// Utilisation du deuxième cursor pour introduire les produits dans la commande
		Vector<HashMap<Product, Integer> > contentOrder = new Vector<HashMap<Product, Integer> >();
		ProductDatabase productDatabase = new ProductDatabase(databaseQueries);
		while (cursorToBeIn.moveToNext())
		{
			HashMap<Product, Integer> numberProduct = new HashMap<Product, Integer>();
			
			// Quantité du produit dans la commande
			
			Product product = productDatabase.getProductFromId(cursorToBeIn.getInt(0));
			numberProduct.put(product, cursorToBeIn.getInt(1));
			contentOrder.add(numberProduct);
		}
		cursorToBeIn.close();
		order.setContentOrder(contentOrder);
		
		return order;
	}
}
